package L01;
//阻塞队列的代码具体实现
//生产者   消费者模型

class MyBlockingQueue{
    //队列：  1.环形数组   2.链表
    //static  属性，所有的类的实例都共用这几个变量
    private static String[]queue=new String[1000];

    //下面的三个变量都  进行判定，然后进行修改，有可能会触发内存可见性问题
    private static volatile int head=0;
    private static volatile int tail=0;
    private static volatile int size=0;

    //存函数
    public  void put(String elem) throws InterruptedException {
        synchronized (this){
            if(size== queue.length){
                //队列满了无法加入新元素，直接返回
                //无法执行加元素操作，则会进入阻塞
                this.wait ();
            }
            queue[tail]=elem;
            tail++;
            if(tail== queue.length){
                tail=0;
            }
            size++;
            this.notify ();
        }
    }


    //取函数
    public  String take() throws InterruptedException {
        synchronized (this){
            if(size==0){//队列为空，无法返回
                //进入阻塞
                this.wait ();
            }

            String h=queue[head];
            head++;
            if(head== queue.length){
                head=0;
            }
            size--;
            this.notify ();//唤醒put（）中的wait
            return h;
        }

    }

}

public class T24 {
    public static void main (String[] args) {
        MyBlockingQueue queue=new MyBlockingQueue ();
        //生产者
        Thread t1=new Thread (()->{
            int num=1;
            while(true){
                try {
                    queue.put(num+"");
                    System.out.println ("生产"+num);
                    num++;
                    Thread.sleep (1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException (e);
                }


            }
        });

        //消费者
        Thread t2=new Thread (()->{
            while(true){
                try {
                    String ou=queue.take ();
                    System.out.println ("消耗了"+ou);
                } catch (InterruptedException e) {
                    throw new RuntimeException (e);
                }
            }


        });

        t1.start ();
        t2.start ();


    }
}

